﻿using DG.Tweening;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class BloodChangeUI : BaseMeshEffect
{
    public Vector3 pos = new Vector3(0, 0, 0);

    [SerializeField]
    private float m_spacing = 0f;

    [SerializeField]
    private Color m_EffectColor = new Color(0f, 0f, 0f, 0.5f);

    [SerializeField]
    private Vector2 m_EffectDistance = new Vector2(1f, -1f);

    [SerializeField]
    private bool m_UseGraphicAlpha = true;

    private float time;

    private Text text;

    private bool update = true;

    private Camera UICamera;

    public void Start()
    {
        time = Time.time;
        text = GetComponent<Text>();
        UICamera = GameObject.Find("UICamera").GetComponent<Camera>();
        DOTween.To(() => pos, (r) =>
        {
            Vector3 vppos = Camera.main.WorldToViewportPoint(r);
            Vector3 uiPos = UICamera.ViewportToWorldPoint(vppos);
            transform.position = uiPos;
        }, pos + new Vector3(0, 2f, 0), 2f).OnComplete(()=>
        {
            GameObject.Destroy(this.gameObject);
        });

        DOTween.To(() => 1.0f, (c) =>
        {
            text.color = new Color(text.color.r, text.color.g, text.color.b,c);
            effectColor = new Color(effectColor.r, effectColor.g, effectColor.b, c);
        }, 0.0f, 1.0f).SetEase(Ease.InCirc);
        TimerMaster.setTimeout(() => update = false, Mathf.Max((int)(showSpeed * text.text.Length * 1000), 1000));
    }

    public void Update()
    {
        if (update)
        {
            graphic.SetVerticesDirty();
        }
    }

    public Color effectColor
    {
        get
        {
            return this.m_EffectColor;
        }
        set
        {
            this.m_EffectColor = value;
            if (base.graphic != null)
            {
                base.graphic.SetVerticesDirty();
            }
        }
    }

    public Vector2 effectDistance
    {
        get
        {
            return this.m_EffectDistance;
        }
        set
        {
            if (value.x > 600f)
            {
                value.x = 600f;
            }
            if (value.x < -600f)
            {
                value.x = -600f;
            }
            if (value.y > 600f)
            {
                value.y = 600f;
            }
            if (value.y < -600f)
            {
                value.y = -600f;
            }
            if (this.m_EffectDistance == value)
            {
                return;
            }
            this.m_EffectDistance = value;
            if (base.graphic != null)
            {
                base.graphic.SetVerticesDirty();
            }
        }
    }

    public bool useGraphicAlpha
    {
        get
        {
            return this.m_UseGraphicAlpha;
        }
        set
        {
            this.m_UseGraphicAlpha = value;
            if (base.graphic != null)
            {
                base.graphic.SetVerticesDirty();
            }
        }
    }

    protected void ApplyShadow(List<UIVertex> verts, Color32 color, int start, int end, float x, float y)
    {
        int num = verts.Count * 2;
        if (verts.Capacity < num)
        {
            verts.Capacity = num;
        }
        for (int i = start; i < end; i++)
        {
            UIVertex uIVertex = verts[i];
            verts.Add(uIVertex);

            Vector3 position = uIVertex.position;
            //Debug.Log("vertex pos: "+position);
            position.x += x;
            position.y += y;
            uIVertex.position = position;
            Color32 color2 = color;
            if (this.m_UseGraphicAlpha)
            {
                color2.a = (byte)(color2.a * verts[i].color.a / 255);
            }
            uIVertex.color = color2;
            //uIVertex.color = (Color32)Color.blue;
            verts[i] = uIVertex;
        }
    }


    protected BloodChangeUI() { }

#if UNITY_EDITOR
    protected override void OnValidate()
    {
        spacing = m_spacing;
        base.OnValidate();
    }
#endif

    public float spacing
    {
        get { return m_spacing; }
        set
        {
            if (m_spacing == value) return;
            m_spacing = value;
            if (graphic != null) graphic.SetVerticesDirty();
        }
    }

    public float showSpeed = 0.1f;

    public override void ModifyMesh(VertexHelper vh)
    {
        if (!IsActive()) return;

        // 从mesh 得到 顶点集
        List<UIVertex> verts = new List<UIVertex>();
        List<UIVertex> res = new List<UIVertex>();
        vh.GetUIVertexStream(verts);

        Text text = GetComponent<Text>();
        if (text == null)
        {
            Debug.LogWarning("LetterSpacing: Missing Text component");
            return;
        }

        string[] lines = text.text.Split('\n');
        Vector3 pos;
        float letterOffset = spacing * (float)text.fontSize / 100f;
        float alignmentFactor = 0;
        int glyphIdx = 0;

        switch (text.alignment)
        {
            case TextAnchor.LowerLeft:
            case TextAnchor.MiddleLeft:
            case TextAnchor.UpperLeft:
                alignmentFactor = 0f;
                break;

            case TextAnchor.LowerCenter:
            case TextAnchor.MiddleCenter:
            case TextAnchor.UpperCenter:
                alignmentFactor = 0.5f;
                break;

            case TextAnchor.LowerRight:
            case TextAnchor.MiddleRight:
            case TextAnchor.UpperRight:
                alignmentFactor = 1f;
                break;
        }

        for (int lineIdx = 0; lineIdx < lines.Length; lineIdx++)
        {
            string line = lines[lineIdx];
            float lineOffset = (line.Length - 1) * letterOffset * alignmentFactor;
            var length = (Time.time - time) / showSpeed;

            for (int charIdx = 0; charIdx < Mathf.Min(length, line.Length); charIdx++)
            {
                float atTime = Time.time - time - charIdx * showSpeed;
                if (atTime < 0)
                {
                    atTime = 0;
                }
                if (atTime > showSpeed)
                {
                    atTime = showSpeed;
                }
                int idx1 = glyphIdx * 6 + 0;
                int idx2 = glyphIdx * 6 + 1;
                int idx3 = glyphIdx * 6 + 2;
                int idx4 = glyphIdx * 6 + 3;
                int idx5 = glyphIdx * 6 + 4;
                int idx6 = glyphIdx * 6 + 5;

                if (idx6 > verts.Count - 1) return;

                UIVertex vert1 = verts[idx1];
                UIVertex vert2 = verts[idx2];
                UIVertex vert3 = verts[idx3];
                UIVertex vert4 = verts[idx4];
                UIVertex vert5 = verts[idx5];
                UIVertex vert6 = verts[idx6];

                pos = Vector3.right * (letterOffset * charIdx - lineOffset) + Vector3.down * (atTime - showSpeed) * -200;

                vert1.position += pos;
                vert2.position += pos;
                vert3.position += pos;
                vert4.position += pos;
                vert5.position += pos;
                vert6.position += pos;

                res.Add(vert1);
                res.Add(vert2);
                res.Add(vert3);
                res.Add(vert4);
                res.Add(vert5);
                res.Add(vert6);

                glyphIdx++;
            }

            glyphIdx++;
        }

        verts = res;

        Text foundtext = text;

        float best_fit_adjustment = 1f;

        if (foundtext && foundtext.resizeTextForBestFit)
        {
            best_fit_adjustment = (float)foundtext.cachedTextGenerator.fontSizeUsedForBestFit / (foundtext.resizeTextMaxSize - 1); //max size seems to be exclusive

        }

        float distanceX = this.effectDistance.x * best_fit_adjustment;
        float distanceY = this.effectDistance.y * best_fit_adjustment;

        int start = 0;
        int count = verts.Count;
        this.ApplyShadow(verts, this.effectColor, start, verts.Count, distanceX, distanceY);
        start = count;
        count = verts.Count;
        this.ApplyShadow(verts, this.effectColor, start, verts.Count, distanceX, -distanceY);
        start = count;
        count = verts.Count;
        this.ApplyShadow(verts, this.effectColor, start, verts.Count, -distanceX, distanceY);
        start = count;
        count = verts.Count;
        this.ApplyShadow(verts, this.effectColor, start, verts.Count, -distanceX, -distanceY);

        start = count;
        count = verts.Count;
        this.ApplyShadow(verts, this.effectColor, start, verts.Count, distanceX, 0);
        start = count;
        count = verts.Count;
        this.ApplyShadow(verts, this.effectColor, start, verts.Count, -distanceX, 0);

        start = count;
        count = verts.Count;
        this.ApplyShadow(verts, this.effectColor, start, verts.Count, 0, distanceY);
        start = count;
        count = verts.Count;
        this.ApplyShadow(verts, this.effectColor, start, verts.Count, 0, -distanceY);

        vh.AddUIVertexTriangleStream(verts);
    }

    public Color setA(Color32 c, float a)
    {
        c.a = (byte)(a * 255);
        return c;
    }
}